import * as Three from 'three';

interface VECTOR3 {
  x: number;
  y: number;
  z: number;
}
class CalcClass {
  /*
	------------------------------------------
	| 计算向量B<Vector3>在向量A<Vector3>的投影;返回一个标量
  | return number
	------------------------------------------ */
  vecProjection(A: any, B: any) {
    // 计算A的单位向量
    const AUnit = A.clone().normalize();

    // 计算B在A方向上的投影
    return B.dot(AUnit);
  }

  vecProjectionDir(A: any, B: any) {
    const AUnit = A.clone().normalize();
    // 计算B在A方向上的投影
    const projection = this.vecProjection(A, B);

    // 计算在A方向上的分量向量
    const componentA = AUnit.clone().multiplyScalar(projection);

    // 计算垂直于A方向的分量向量
    return B.clone().sub(componentA);
  }

  /**
   * 计算三维物体在窗口上的投射位置
   * position; camera; div;
   * **/
  toScreenXY(position: any, camera: any, div: any) {
    var pos = position.clone();
    const projScreenMat = camera.projectionMatrix
      .clone()
      .multiply(camera.matrixWorldInverse);
    projScreenMat.multiplyVector3(pos);

    var offset = this.findOffset(div);

    return {
      x: ((pos.x + 1) * div.width) / 2 + offset.left,
      y: ((-pos.y + 1) * div.height) / 2 + offset.top,
    };
  }
  findOffset(element: any) {
    var pos: any = new Object();
    pos.left = pos.top = 0;
    if (element.offsetParent) {
      do {
        pos.left += element.offsetLeft;
        pos.top += element.offsetTop;
      } while ((element = element.offsetParent));
    }
    return pos;
  }

  /**
   * 经纬度转换为三维点
   * @param {Number} opts.lat 纬度 -90 ~ 90
   * @param {Number} opts.lng 经度 -180 ~ 180
   * @param {Number} opts.radius 半径
   * @returns {Vector3}
   * **/
  latLongToVector3(opts: { lat: number; lng: number; radius: number }) {
    opts = opts || {};
    var lat = opts.lat,
      lng = opts.lng,
      radius = opts.radius;
    var phi = (180 + lng) * (Math.PI / 180); //经度角度
    var theta = (90 - lat) * (Math.PI / 180); //纬度角度
    var x = -radius * Math.sin(theta) * Math.cos(phi);
    var y = radius * Math.cos(theta);
    var z = radius * Math.sin(theta) * Math.sin(phi);
    return { x, y, z };
  }
}

const CalcThree = new CalcClass();
export default CalcThree;
